home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / Snippets / QuickDraw / SeedCFill Example / SeedCFill Example.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-02  |  7.5 KB  |  264 lines  |  [TEXT/KAHL]

  1. /****************************************************************************/
  2. /*                                                                            */
  3. /*    Application:    SeedCFill Example                                        */
  4. /*                                                                            */
  5. /*    Description:    This snippet shows how to use the SeedCFill routine        */
  6. /*                    to create a mask given a source image. As decribed        */
  7. /*                    on page 71 of Inside Mac volume V, this routine            */
  8. /*                    computes a destination bitmap image with 1's only        */
  9. /*                    in the pixels where paint can not leak from the            */
  10. /*                    starting seed point. This is similar to the paint-        */
  11. /*                    bucket tool.                                            */
  12. /*                                                                            */
  13. /*    File:            SeedCFill Example.π                                        */
  14. /*                    SeedCFill Example.c                                        */
  15. /*                    SeedCFill Example.π.rsrc                                */
  16. /*                                                                            */
  17. /*    Programmer:        Edgar Lee                                                */
  18. /*    Organization:    Apple Computer, Inc.                                    */
  19. /*    Department:        Developer Technical Support, DTS                        */
  20. /*    Language:        C (Think C version 5.0.2)                                */
  21. /*    Date Created:    10-19-92                                                */
  22. /*                                                                            */
  23. /****************************************************************************/
  24.  
  25. /* Constant Declarations */
  26.  
  27. #define    WWIDTH        (176 * 2)
  28. #define    WHEIGHT        (106 * 2)
  29.  
  30. #define WLEFT        (((screenBits.bounds.right - screenBits.bounds.left) - WWIDTH) / 2)
  31. #define WTOP        (((screenBits.bounds.bottom - screenBits.bounds.top) - WHEIGHT) / 2)
  32.  
  33. /* Global Variable Definitions */
  34.  
  35. WindowPtr    gWindow;
  36.  
  37. void initMac();
  38. void createWindow();
  39. void doSeedCFillExample();
  40.  
  41. void DisposeGrafPort();
  42. GrafPtr CreateGrafPort();
  43.  
  44. void doEventLoop();
  45.  
  46. main()
  47. {
  48.     initMac();
  49.     createWindow();
  50.     doEventLoop();
  51. }
  52.  
  53. void initMac()
  54. {
  55.     MaxApplZone();
  56.     
  57.     InitGraf( &thePort );
  58.     InitFonts();
  59.     InitWindows();
  60.     InitMenus();
  61.     TEInit();
  62.     InitDialogs( nil );
  63.     InitCursor();
  64.     FlushEvents( 0, everyEvent );
  65. }
  66.  
  67. void createWindow()
  68. {
  69.     Rect            rect;
  70.     PaletteHandle    palette;
  71.     
  72.     SetRect( &rect, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
  73.     
  74.     gWindow = NewCWindow( 0L, &rect, "\pClick anywhere in left image.", true, documentProc,
  75.                             (WindowPtr)-1L, true, 0L );
  76.                             
  77.     SetPort( gWindow );
  78.  
  79.     /****************************************************************************/    
  80.     /* Attach a palette of the default colortable to the window.                */
  81.     /*  WARNING: SeedCFill may not work if the current gDevice's colortable is     */
  82.     /*    different than that of the offscreen's colortable.  This offscreen is     */
  83.     /*    the one passed into SeedCFill.  To eliminate this problem, we attach a    */
  84.     /*    palette contaning the same colors used by the offscreen to the window.    */
  85.     /****************************************************************************/
  86.     
  87.     palette = NewPalette( 256, GetCTable( 8 ), pmTolerant, 0 );
  88.     SetPalette( gWindow, palette, true );
  89. }
  90.  
  91. void doSeedCFillExample( point )
  92. Point    point;
  93. {
  94.     PicHandle        pict;                /* Pict used for the source. */
  95.     GWorldPtr        source;                /* Gworld used to store the pict. */
  96.     PixMapHandle    sourcePixMap;        /* Handle to the source Gworld. */
  97.     GrafPtr            mask;                /* BitMap used for creating the mask. */
  98.     int                seedH, seedV;        /* Pixel position used to determine the mask. */
  99.     Rect            rect;                /* Bounding rect of mask and source. */
  100.     CGrafPtr        currentPort;        /* Saved CGrafPtr for later restore. */
  101.     GDHandle        currentDevice;        /* Saved device for later restore. */
  102.     
  103.     /* Load the pict resource to be used for the source. */
  104.     pict = (PicHandle)GetResource( 'PICT', 128 );
  105.  
  106.     /* Define the bounding rect for the source and mask. */
  107.     rect = (**pict).picFrame;
  108.     OffsetRect( &rect, -rect.left, -rect.top );
  109.     rect.right *= 2;
  110.     rect.bottom *= 2;
  111.     
  112.     /* Draw the source image in the window to see what the mask will be created from. */
  113.     DrawPicture( pict, &rect );
  114.     HPurge( pict );
  115.     
  116.     /* Return if mouse click was not within the source rect. */
  117.     if (point.h < rect.left || point.h > rect.right ||
  118.         point.v < rect.top || point.v > rect.bottom)
  119.             return;
  120.  
  121.     /* Create a gworld to store the pict. */
  122.     NewGWorld( &source, 8, &rect, GetCTable( 8 ), nil, 0 );
  123.     sourcePixMap = GetGWorldPixMap( source );
  124.     
  125.     /* Draw the pict into the gworld. */
  126.     GetGWorld( ¤tPort, ¤tDevice );
  127.     SetGWorld( source, nil );
  128.     DrawPicture( pict, &rect );
  129.     SetGWorld( currentPort, currentDevice );
  130.         
  131.     /* Allocate a bitmap for the mask. */
  132.     mask = CreateGrafPort( &(**sourcePixMap).bounds );
  133.  
  134.     /* Use the mouse click as the starting seed position. */
  135.     seedH = point.h;
  136.     seedV = point.v;
  137.     
  138.     /* Create a mask from the source, starting from the seed point. */
  139.     SeedCFill( (BitMap *)*sourcePixMap, &(*mask).portBits, &(**sourcePixMap).bounds,
  140.                 &(*mask).portRect, seedH, seedV, nil, 0 );
  141.         
  142.     /* Draw a red cross where the mouse was last clicked. */
  143.     ForeColor( redColor );
  144.     MoveTo( rect.left + seedH - 2, seedV );
  145.     LineTo( rect.left + seedH + 2, seedV );
  146.     MoveTo( rect.left + seedH, seedV - 2 );
  147.     LineTo( rect.left + seedH, seedV + 2 );
  148.     ForeColor( blackColor );
  149.     
  150.     OffsetRect( &rect, (**sourcePixMap).bounds.right, 0 );
  151.     EraseRect( &rect );
  152.     
  153.     /* Copy the source to the window while applying the mask. */
  154.     CopyMask( (BitMap *)*sourcePixMap, &((GrafPtr)mask)->portBits, &gWindow->portBits,
  155.                 &(**sourcePixMap).bounds, &((GrafPtr)mask)->portRect, &rect );
  156.     
  157.     /* Release the used memory. */
  158.     DisposeGrafPort( (GrafPtr)mask );
  159.     DisposeGWorld( source );
  160. }
  161.  
  162. GrafPtr CreateGrafPort( bounds )    /* CreateGrafPort originally written by Forrest Tanaka. */
  163. Rect *bounds;
  164. {
  165.     GrafPtr    savedPort;        /* Saved GrafPtr for later restore. */
  166.     GrafPtr    newPort;        /* New GrafPort. */
  167.     Rect    localBounds;    /* Local copy of bounds. */
  168.  
  169.     GetPort( &savedPort );
  170.  
  171.     /* Set the top-left corner of bounds to (0,0). */
  172.     localBounds = *bounds;
  173.     OffsetRect( &localBounds, -bounds->left, -bounds->top );
  174.  
  175.     /* Allocate a new GrafPort. */
  176.     newPort = (GrafPtr)NewPtrClear( sizeof( GrafPort ) );
  177.     
  178.     if (newPort != nil)
  179.     {
  180.         /* Initialize the new port and make the current port. */
  181.         OpenPort( newPort );
  182.  
  183.         /* Initialize and allocate the bitmap. */
  184.         newPort->portBits.bounds = localBounds;
  185.           newPort->portBits.rowBytes = ((localBounds.right + 15) >> 4) << 1;
  186.         newPort->portBits.baseAddr =  NewPtrClear( newPort->portBits.rowBytes *
  187.                                                     (long)localBounds.bottom );
  188.         if (newPort->portBits.baseAddr != nil)
  189.         {
  190.             /* Clean up the new port. */
  191.             newPort->portRect = localBounds;
  192.             ClipRect( &localBounds );
  193.             RectRgn( newPort->visRgn, &localBounds );
  194.             EraseRect( &localBounds );
  195.         }
  196.         else
  197.         {
  198.             /* Allocation failed; deallocate the port. */
  199.             ClosePort( newPort );
  200.             DisposPtr( (Ptr)newPort );
  201.             newPort = nil;
  202.         }
  203.     }
  204.     
  205.     SetPort( savedPort );
  206.     return newPort;
  207. }
  208.  
  209. void DisposeGrafPort( doomedPort )    /* DisposeGrafPort originally written by Forrest Tanaka. */
  210. GrafPtr doomedPort;
  211. {
  212.     ClosePort( doomedPort );
  213.     DisposPtr( doomedPort->portBits.baseAddr );
  214.     DisposPtr( (Ptr)doomedPort );
  215. }
  216.  
  217. void doEventLoop()
  218. {
  219.     EventRecord        event;
  220.     WindowPtr        window;
  221.     short            clickArea;
  222.     Rect              screenRect;
  223.     static Point    point = { -1, -1 };
  224.     
  225.     for (;;)
  226.     {
  227.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  228.         {
  229.             if (event.what == mouseDown)
  230.             {
  231.                 clickArea = FindWindow( event.where, &window );
  232.                 
  233.                 if (clickArea == inDrag)
  234.                 {
  235.                     screenRect = (**GetGrayRgn()).rgnBBox;
  236.                     DragWindow( window, event.where, &screenRect );
  237.                 }
  238.                 else if (clickArea == inContent)
  239.                 {
  240.                     if (window != FrontWindow())
  241.                         SelectWindow( window );
  242.                     else
  243.                     {
  244.                         point = event.where;
  245.                         GlobalToLocal( &point );
  246.                         doSeedCFillExample( point );
  247.                     }
  248.                 }
  249.                 else if (clickArea == inGoAway)
  250.                     if (TrackGoAway( window, event.where ))
  251.                         return;
  252.             }
  253.             else if (event.what == updateEvt)
  254.             {
  255.                 window = (WindowPtr)event.message;    
  256.                 SetPort( window );
  257.                 
  258.                 BeginUpdate( window );
  259.                 doSeedCFillExample( point );
  260.                 EndUpdate( window );
  261.             }
  262.         }
  263.     }
  264. }